using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using CWM.Skinn;

public class CC3BlendShapesFixInspector
{
    public CC3SubMeshHeadType fixType;
    public Transform fixRoot;
    public List<Transform> fixRootsList; //所有命名为_FixList的结点列表
    public BlendshapeController blendshapeController;
    public SkinnedMeshRenderer fixSkinMeshRenderer;

    public List<MeshFilter> replaceFiltersList; //选中被替换的MeshFilter
    public SkinnShapeLoaderWizard wizard;

    public CC3BlendShapesFixInspector()
    {
        replaceFiltersList = new List<MeshFilter>();
    }

    public void OnGUI()
    {
        GUILayout.Space(10);
        GUILayout.Label("\t调整角色的骨骼，使角色表情正确，添加需要被替换的节点，进行替换");
        GUILayout.Space(10);

        EditorGUILayout.BeginHorizontal();
        {
            fixType = (CC3SubMeshHeadType)EditorGUILayout.EnumPopup("纠正部位类型：", fixType);
            if (GUILayout.Button("1.根据类型获取纠正部位列表根节点"))
            {
                RefreshFixListRoot();
                RefreshFixSkinMeshRenderer();
            }
        }
        EditorGUILayout.EndHorizontal();

        fixRoot = EditorGUILayout.ObjectField("纠正部位列表根结点：", fixRoot, typeof(Transform), SkinnProCustomUtility.ObjectFieldOption()) as Transform;
        blendshapeController = EditorGUILayout.ObjectField("BlendShape总控制器：", blendshapeController, typeof(BlendshapeController), SkinnProCustomUtility.ObjectFieldOption()) as BlendshapeController;
        fixSkinMeshRenderer = EditorGUILayout.ObjectField("被纠正的蒙皮：", fixSkinMeshRenderer, typeof(SkinnedMeshRenderer), SkinnProCustomUtility.ObjectFieldOption()) as SkinnedMeshRenderer;
        if (fixRoot == null)
        {
            return;
        }

        GUILayout.Space(10);

        DrawReplaceMeshesList();

        GUILayout.Space(10);

        if (!CheckReplaceFiltersListValid())
        {
            GUI.enabled = false;
        }
        if (GUILayout.Button("2.烘焙修复的Mesh并替换错误的"))
        {
            BakeFixedMeshRendererAndReplaceWrong();
        }
        GUI.enabled = true;

        GUILayout.Space(10);

        if (GUILayout.Button("3.覆盖 " + fixSkinMeshRenderer.name + " 原有的BlendShapes信息"))
        {
            OverrideFixSkinBlendShapes();
        }
    }

    private void BakeFixedMeshRendererAndReplaceWrong()
    {
        var bakeMesh = Bake2MeshRenderer();
        if (bakeMesh == null)
        {
            return;
        }

        for (int i = 0; i < replaceFiltersList.Count; i++)
        {
            var bakeFilter = bakeMesh.GetComponent<MeshFilter>();
            replaceFiltersList[i].mesh = bakeFilter.sharedMesh;
        }

        Move2TempRoot(bakeMesh);
    }

    /// <summary>
    /// 检查需要被替换的列表是否有效
    /// </summary>
    private bool CheckReplaceFiltersListValid()
    {
        if (replaceFiltersList == null || replaceFiltersList.Count == 0)
        {
            return false;
        }

        for (int i = 0; i < replaceFiltersList.Count; i++)
        {
            if (replaceFiltersList[i] == null)
            {
                return false;
            }
        }

        return true;
    }

    /// <summary>
    /// 根据修改好的_FixList 覆盖原来SkinMeshRenderer上的BlendShapes信息
    /// </summary>
    private void OverrideFixSkinBlendShapes()
    {
        wizard = SkinnProCustomMain.ShapeLoad2SkinMeshRenderer(fixSkinMeshRenderer);
        wizard.clearOldShapes = true;

        var childs = fixRoot.GetAllChildren(false);
        var gos = new List<GameObject>();
        for (int i = 0; i < childs.Count; i++)
        {
            gos.Add(childs[i].gameObject);
        }

        wizard.shapeRenderers = gos.ToArray();
    }

    private GameObject Bake2MeshRenderer()
    {
        Selection.activeGameObject = fixSkinMeshRenderer.gameObject;
        using (var record = new SkinnProCustomUtility.TimeRecord("烘焙修复的Mesh"))
        {
            SkinnProCustomMain.Bake2MeshRenderer();
        }

        return Selection.activeGameObject;
    }

    private void RefreshFixListRoot()
    {
        if (fixRootsList == null || fixRootsList.Count == 0) //单独开启纠正窗口时 通过name去查找 要注意_FixList的显隐状态
        {
            fixRoot = GameObject.Find(fixType.ToString() + "_FixList")?.transform;
            if (fixRoot == null)
            {
                Debug.LogError("注意：单独开启纠正窗口时,是通过name去查找,要注意_FixList的显隐状态,如果都是显示状态还是获取不到fixRoot,重新打开该窗口");
            }

            return;
        }

        for (int i = 0; i < fixRootsList.Count; i++)
        {
            if (fixRootsList[i].name.Contains(fixType.ToString()))
            {
                fixRoot = fixRootsList[i];

                return;
            }
        }
    }

    private void RefreshFixSkinMeshRenderer()
    {
        blendshapeController = GameObject.FindObjectOfType<BlendshapeController>();
        if (blendshapeController)
        {
            var smrs = blendshapeController.GetComponentsInChildren<SkinnedMeshRenderer>(true);
            for (int i = 0; i < smrs.Length; i++)
            {
                if (smrs[i].name.Contains(fixType.ToString()))
                {
                    fixSkinMeshRenderer = smrs[i];

                    return;
                }
            }
        }
    }

    private void DrawReplaceMeshesList()
    {
        if (replaceFiltersList == null)
        {
            replaceFiltersList = new List<MeshFilter>();

            return;
        }

        if (GUILayout.Button("增加需要被替换的MeshRenderer"))
        {
            replaceFiltersList.Add(null);
        }

        for (int i = 0; i < replaceFiltersList.Count; i++)
        {
            replaceFiltersList[i] = EditorGUILayout.ObjectField("被替换节点的网格_" + i, replaceFiltersList[i], typeof(MeshFilter)) as MeshFilter;
        }

        if (replaceFiltersList.Count > 0)
        {
            if (GUILayout.Button("移除末位"))
            {
                replaceFiltersList.RemoveAt(replaceFiltersList.Count - 1);
            }
        }
    }

    private void Move2TempRoot(GameObject tempGo)
    {
        tempGo.transform.SetParent(SkinnProCustomUtility.TempRoot);
        tempGo.SetActive(false);
    }

    public void AutoExecute(CC3BlendShapesFixData fixData, Transform fixBone)
    {
        foreach (var name in fixData.fixBlendShapesNamesList)
        {
            var meshFilter = fixRoot.Get(name)?.GetComponent<MeshFilter>();
            if (meshFilter == null)
            {
                continue;
            }

            replaceFiltersList.Add(meshFilter);
        }

        fixBone.localPosition += fixData.fixOffset.positionOffset;
        fixBone.localEulerAngles += fixData.fixOffset.rotationOffset;

        BakeFixedMeshRendererAndReplaceWrong();
        OverrideFixSkinBlendShapes();

        SkinnProCustomWindow.Instance.GetInspector().ResetBonesInfo();

        wizard.Create();
        wizard.Close();
    }
}
